package com.yunji.common.framework;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.yunji.common.utils.Pair;

/**
 * @author : peter-zhu
 * @date : 2024/10/25 11:47
 * @description : TODO
 **/
public class MybatisPlusHelper {

    private static final String JSON_CONTAINS_ONE_VALUE = "JSON_CONTAINS(%s,'%s')";

    public static <T> String jsonContains(SFunction<T, ?> column, Object value) {
        if (value == null) {
            return null;
        }
        String rs = value instanceof String ? "\"" + value + "\"" : value.toString();
        return String.format(JSON_CONTAINS_ONE_VALUE, getColumnName(column), rs);
    }

    public static <T> String columnAddCount(SFunction<T, ?> column, Number value) {
        if (value == null) {
            value = 0;
        }
        String columnName = getColumnName(column);
        return columnName + "=" + columnName + "+" + value;
    }

    public static <T> String aliasCondition(SFunction<T, ?> column, String alias) {
        if (alias == null) {
            return null;
        }
        return String.join(alias, ".", getColumnName(column));
    }

    /**
     * @param : 表名
     * @return : select 1 from a where id=1
     * @author : peter-zhu
     * @date : 2024/10/29 14:33
     * @description : TODO
     * @param: 列名
     * @param: 列名要传的值
     */
    public static <T> String addExistsSql(Class<T> cls, SFunction<T, ?> column, Object value) {
        String tableName = SqlHelper.table(cls).getTableName();
        String rs = value instanceof String ? "'" + value + "'" : value.toString();
        return String.format("and %s.%s=%s", tableName, getColumnName(column), rs);
    }

    public static <X,Y> String buildExistsSql(Class<X> existsTable, SFunction<X, ?> existsColumn, Class<Y> outerTable, SFunction<Y, ?> outerColumn) {
        String existsTab = SqlHelper.table(existsTable).getTableName();
        String outerTab = SqlHelper.table(outerTable).getTableName();
        return String.format("select 1 from %s where %s.%s=%s.%s", existsTab, existsTab, getColumnName(existsColumn), outerTab, getColumnName(outerColumn));
    }

    public static String camelToSnake(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }

    //FIXME  这里反射机制消耗性能以及内存 后期优化做反射缓存
    public static <T> String getColumnName(Class<T> clazz, SFunction<T, ?> column) {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
        if (tableInfo == null) {
            throw new RuntimeException("无法找到对应的表信息");
        }
        return tableInfo.getFieldList().stream()
                .filter(fieldInfo -> fieldInfo.getProperty().equals(LambdaUtils.extract(column).getImplMethodName()))
                .findFirst()
                .map(TableFieldInfo::getColumn)
                .orElseThrow(() -> new RuntimeException("无法找到对应的列名"));
    }

    //FIXME  这里反射机制消耗性能以及内存 后期优化做反射缓存
    public static <T> String getColumnName(SFunction<T, ?> fieldName) {
        return camelToSnake(com.github.yulichang.toolkit.LambdaUtils.getName(fieldName));
    }
}
